package com.lianqi.emcpframework.design.support.event;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lianqi.emcpframework.design.domain.event.DomainEvent;
import com.lianqi.emcpframework.design.domain.event.DomainEventExecutor;

/**
 * @program emcp-framework
 * @ClassName BaseDomainEventExecutor
 * @description: 基础领域事件执行器
 * @author: sky
 * @create: 2019/06/06 19:44
 */
public class BaseDomainEventExecutor implements DomainEventExecutor {

    private static final Logger LOGGER = LoggerFactory.getLogger(BaseDomainEventExecutor.class);

    private final ExecutorService executorService;

    /**
     * 构造方法
     * 
     * @param name
     *            线程池名称
     * @param nThreads
     *            最大线程数
     * @param buffer
     *            线程队列大小
     */
    public BaseDomainEventExecutor(String name, int nThreads, int buffer) {
        // 开启守护线程
        BasicThreadFactory threadFactory = new BasicThreadFactory.Builder().namingPattern(name + "-%d").daemon(true)
            .uncaughtExceptionHandler((t, e) -> {
                LOGGER.error("failed to run task on {}.", t, e);
            }).build();
        // 参数列表：线程池大小、最大线程数、存活时间、时间单位、线程队列、线程工厂类、线程执行器
        this.executorService = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingDeque<Runnable>(buffer), threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
    }

    @Override
    public <E extends DomainEvent> void submit(Task<E> task) {
        executorService.submit(task);
    }
}
